package cn.itcast.web.shiro;

import cn.itcast.domain.system.Module;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.ModuleService;
import cn.itcast.service.system.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 自定义realm域
 */
public class AuthRealm extends AuthorizingRealm {


    @Autowired
    private UserService userService;

    @Autowired
    private ModuleService moduleService;

    /**
     * 获取授权数据
     *  * 查询当前登录用户，具有的所有模块！
     *  * 获取所有模块的名称
     *  参数：
     *     PrincipalCollection：安全数据集合
     *  返回值：
     *     授权数据（模块名称数组）
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1、获取当前登录用户（安全数据）
        User user = (User)principalCollection.getPrimaryPrincipal(); //唯一的安全数据
        //2、调用模块service，查询模块列表
        List<Module> modules = moduleService.findByUser(user);
        //3、构造模块名称的数组
        Set<String> stringPermissions = new HashSet<>();
        for (Module module : modules) {
            stringPermissions.add(module.getName());
        }
        //4、构造返回值
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(stringPermissions);
        return info;
    }


    /**
     * 获取认证数据
     *   根据用户输入的用户名和密码，完成登录验证过程
     *   参数：
     *      AuthenticationToken：用户输入的用户名和密码
     *   返回值：
     *      AuthenticationInfo：安全数据
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1、获取用户名和密码
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String email = upToken.getUsername();
        String password = new String(upToken.getPassword());
        //2、根据email查询用户
        User user = userService.findByEmail(email);
        //3、判断用户是否存在且密码一致
        if(user != null && user.getPassword().equals(password)) {
            //3.1 如果存在且密码一致，构造返回值
            //构造参数：1.用户对象，2.用户输入的密码,3、realm名称（当前类名）
            return new SimpleAuthenticationInfo(user,password,this.getName());
        }else {
            //3.2 用户不存在或密码不一致，返回null（自动抛出异常）
            return null;
        }
    }
}
